home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 26 / Cream of the Crop 26.iso / doom / chasecam.zip / QC106.ZIP / chasecam.qc next >
Text File  |  1997-04-20  |  24KB  |  1,101 lines

  1. /*
  2. chasecam file
  3. player entity variables used:
  4. .dest_x      (HK WEAP)
  5. .dest1_x     (HUD)
  6. .dest1_y      (MSKIN PRO)
  7. .dest2_x,y,z  (CAM)
  8.  
  9.  #####################
  10.  ### chase cam mod ###
  11.  Rob Albin, 09 Sep 96
  12.  
  13.  orig functions modified:
  14.     WEAPONS.QC
  15.         W_SetCurrentAmmo
  16.         ImpulseCommands
  17.     CLIENT.QC
  18.         SetChangeParms
  19.         SetNewParms
  20.         DecodeLevelParms
  21.         PutClientInServer
  22.  
  23. // ref. defs.qc
  24.  
  25. // message protocol defines
  26. float SVC_SETVIEWPORT    = 5;
  27. float SVC_SETVIEWANGLES    = 10;
  28.  
  29. // free player entity variable
  30. // ('.float speed'  bit-flag defines:) changed:
  31. // player.dest2_x = bit-flag variable
  32. // player.dest2_y = chasecam distance
  33. // player.dest2_z = chasecam zmult (height offset)
  34. float HUD_ON          = 16;
  35. *float CHSCAM_MONSTER  = 8;* deleted *
  36. float CHSCAM_ON       = 4;
  37. float LASERTARG_LIT   = 2;
  38. float LASERTARG_ON    = 1;
  39. */
  40.  
  41.  
  42. void() Keep_cam_chasing_owner;
  43. void( float opt ) Remove_chase_cam;
  44.  
  45. // (moved to defs.qc)
  46. //float chasecam_dist = 118, chasecam_zmult = 0.30000;
  47. // changed to player.dest2_y (distance)
  48. // player.dest2_z (zmult)
  49. // set in client.qc for initial values
  50.  
  51. // Resets weapon model after changing view
  52. // called by chase cam or player entities
  53. void( entity player_ent ) Chase_cam_setweapon =
  54. {
  55.     local entity e;
  56.  
  57.     e = self;
  58.     self = player_ent;
  59.     if ( (self.dest2_x & CHSCAM_ON) ) self.weaponmodel = "";
  60.     else                            W_SetCurrentAmmo ();
  61.     self = e;
  62. };
  63.  
  64. // called either by player or chase cam entities (to restart)
  65. // vpos:
  66. // '0 0 0' = start from player
  67. // (else use as cam origin)
  68. void( entity cam_owner, vector vpos ) Start_chase_cam =
  69. {
  70.  
  71.     local entity    chase_cam;
  72.  
  73.     stuffcmd( cam_owner, "fov 80\n" );
  74.  
  75.     chase_cam = spawn();
  76.  
  77.     chase_cam.owner=cam_owner;
  78.  
  79.     // turn on bit-flag
  80.     chase_cam.owner.dest2_x = chase_cam.owner.dest2_x | CHSCAM_ON;
  81.  
  82.     chase_cam.solid = SOLID_NOT;
  83.     chase_cam.movetype = MOVETYPE_FLY;
  84.  
  85.  
  86.     chase_cam.angles = chase_cam.owner.angles;
  87.  
  88.     setmodel (chase_cam, "progs/eyes.mdl" );
  89.     setsize (chase_cam, '0 0 0', '0 0 0');
  90.  
  91.     if (vpos == '0 0 0')
  92.         setorigin( chase_cam, chase_cam.owner.origin + '0 0 22' );
  93.     else
  94.         setorigin( chase_cam, vpos );
  95.  
  96.     chase_cam.classname = "chase_cam";
  97.  
  98.     chase_cam.nextthink = time + 0.1;
  99.     chase_cam.think = Keep_cam_chasing_owner;
  100.  
  101.     // set CLOSE to 0 (ref. PlayerPreThink())
  102.     chase_cam.owner.view_ofs_z = -1;
  103.  
  104.     msg_entity = cam_owner;                         // target of message
  105.     WriteByte (MSG_ONE, SVC_SETVIEWPORT);
  106.     WriteEntity (MSG_ONE, chase_cam);           // view port
  107.  
  108.     Chase_cam_setweapon( cam_owner );
  109.  
  110.     // distance clipping
  111.     chase_cam.ammo_shells = cam_owner.dest2_y / 3;
  112.  
  113. };
  114.  
  115. // secondary think for cam entities
  116. void() Reable_chase_cam =
  117. {
  118.     self.nextthink = time + 0.1;
  119.  
  120.     //if (self.owner.health <= 0)
  121.     if (self.owner.solid == SOLID_NOT)
  122.     {
  123.         //owner died in water, reset .dest2_x flag for respawn
  124.         self.owner.dest2_x = self.owner.dest2_x | CHSCAM_ON;
  125.         remove( self );
  126.         return;
  127.     }
  128.  
  129.     if (self.owner.waterlevel)
  130.         return;
  131.  
  132.     Start_chase_cam( self.owner, '0 0 0' );
  133.     remove( self );
  134.  
  135. };
  136.  
  137.  
  138. // called only by chase cam entities
  139. // opt values
  140. // TRUE = remove completely
  141. // FALSE = remove view but keep alive with Reable_chase_cam();
  142. void( float opt ) Remove_chase_cam =
  143. {
  144.     stuffcmd( self.owner, "fov 90\n" );
  145.  
  146.     // turn off bit-flag
  147.     self.owner.dest2_x = self.owner.dest2_x - (self.owner.dest2_x & CHSCAM_ON);
  148.  
  149.     // set view-point back to normal
  150.     msg_entity = self.owner;      // target of message
  151.     WriteByte (MSG_ONE, SVC_SETVIEWPORT);
  152.     WriteEntity (MSG_ONE, self.owner);           // view port
  153.  
  154.     setmodel( self, "" );
  155.     self.velocity = '0 0 0';
  156.  
  157.     self.owner.view_ofs_z = 22;
  158.  
  159.     Chase_cam_setweapon( self.owner );
  160.  
  161.     if ( !opt )
  162.     {
  163.         self.nextthink = time + 0.1;
  164.         self.think = Reable_chase_cam;
  165.     }
  166.     else
  167.         remove( self );
  168.  
  169. };
  170.  
  171. /*
  172.     main think function for cam entities
  173.         self.ammo_shells = distance clipping
  174.         self.ammo_nails = hang-up flag
  175.  
  176.     .v_angle_x:
  177.         78.8 (max down aim)
  178.         -68.9 (max up aim)
  179. */
  180. void() Keep_cam_chasing_owner =
  181. {
  182.     local vector vtmp1, vtmp2;
  183.     local vector owner_vec, goal, dir;
  184.     local float  dist, cap, f_f;
  185.     //debug var
  186.     // local string s;
  187.  
  188.     self.nextthink = time + 0.1;
  189.  
  190.     // check if player toggled
  191.     if (! (self.owner.dest2_x & CHSCAM_ON))
  192.     {
  193.         Remove_chase_cam( TRUE );
  194.         return;
  195.     }
  196.  
  197.     // if (self.owner.health < 1)
  198.     if (self.owner.solid == SOLID_NOT)
  199.     {
  200.         stuffcmd( self.owner, "fov 90\n" );
  201.  
  202.         // set view-point back to normal
  203.         // and die, but leave .dest2_x flag alone for respawn
  204.         msg_entity = self.owner;      // target of message
  205.         WriteByte (MSG_ONE, SVC_SETVIEWPORT);
  206.         WriteEntity (MSG_ONE, self.owner);           // view port
  207.         remove( self );
  208.         return;
  209.     }
  210.  
  211.     if ( self.owner.waterlevel )
  212.     {
  213.         Remove_chase_cam( FALSE );
  214.         return;
  215.     }
  216.  
  217.     owner_vec = self.owner.origin + '0 0 22';
  218.  
  219.     // get player velocity relative to player's
  220.     // current yaw
  221.     // f_f (based on running calcs (maxspeed = 400)
  222.     //  (back ~= 640, forward ~= 0)
  223.     dir_y = self.owner.v_angle_y;
  224.     makevectors( dir );
  225.     f_f = vlen( (v_forward * 320) - self.owner.velocity );
  226.  
  227.     // held for use after second makevectors call for
  228.     // pulling forward on a down aim
  229.     dir = v_forward;
  230.  
  231. //   local string s;
  232. //   sprint( self.owner, "\n\n f_f = " );
  233. //   s = ftos( f_f );
  234. //   sprint( self.owner, s );
  235. //   sprint( self.owner, "\n f_r = " );
  236. //   s = ftos( f_r );
  237. //   sprint( self.owner, s );
  238. //   sprint( self.owner, "\n" );
  239.  
  240.     // increment fade-back variable
  241.     self.ammo_shells = self.ammo_shells + 4.5;
  242.     if (self.ammo_shells > self.owner.dest2_y)
  243.         self.ammo_shells = self.owner.dest2_y;
  244.  
  245.     makevectors( self.owner.v_angle );
  246.  
  247.     // set spot before clipping
  248.     //.v_angle_x:
  249.     //    78.8 (max down aim)
  250.     //    -68.9 (max up aim)
  251.  
  252.     goal = owner_vec - (v_forward * self.ammo_shells);
  253.     goal_z = goal_z + 14 + (self.ammo_shells * self.owner.dest2_z);
  254.  
  255.     // adjust initial goal
  256.     //////////////////////////////////////////////////
  257.     if (self.owner.v_angle_x > 0)
  258.     {
  259.         // pull forward
  260.         cap = self.owner.v_angle_x;
  261.         if (cap > 56) cap = 56;
  262.         goal = goal + dir * cap;
  263.  
  264.         // pull down
  265.         goal_z = goal_z - (self.owner.v_angle_x * (self.ammo_shells * 0.01));
  266.         cap = self.owner.origin_z + 28;
  267.         if (goal_z < cap)
  268.             goal_z = cap;
  269.     }
  270.  
  271.     // increase height if getting under the player
  272.     if (goal_z < owner_vec_z)
  273.     {
  274.         vtmp1 = goal; vtmp1_z = 0;
  275.         vtmp2 = owner_vec; vtmp2_z = 0;
  276.         cap = vlen( vtmp1 - vtmp2 );
  277.         if (cap < 100)
  278.         {
  279.             goal_z = goal_z + ((100 - cap) * 0.6);
  280.             if ( goal_z > owner_vec_z )
  281.                 goal_z = owner_vec_z;
  282.         }
  283.     }
  284.     //////////////////////////////////////
  285.  
  286.     // clip for brushes
  287.     //////////////////////////////////////
  288.     traceline (owner_vec, goal, FALSE, self.owner);
  289.     // pull a little forward, avoids most hang-ups along walls
  290.     goal = trace_endpos + ( v_forward * 2 );
  291.  
  292.     // clip fade-back variable
  293.     traceline( owner_vec, owner_vec - (v_forward * self.ammo_shells), FALSE, self.owner);
  294.     if (trace_fraction < 1)
  295.     {
  296.         self.ammo_shells = vlen(trace_endpos - owner_vec);
  297.         cap = fabs( self.owner.v_angle_x ) - 10;
  298.         if (cap > 0)
  299.             self.ammo_shells = self.ammo_shells + cap;
  300.     }
  301.  
  302.     traceline (self.origin, goal, FALSE, self.owner );
  303.     if (trace_fraction < 1)
  304.     {
  305.         // half it if blocked
  306.         dir = normalize(goal - owner_vec);
  307.         dist = vlen(goal - owner_vec) * 0.5;
  308.         goal =  owner_vec + dir * dist;
  309.     }
  310.  
  311.     // pad for floors and ceilings
  312.     traceline (goal, goal + '0 0 6', FALSE, self.owner );
  313.     if (trace_fraction < 1 ) goal = trace_endpos - '0 0 6';
  314.     else
  315.     {
  316.         traceline (goal, goal - '0 0 6', FALSE, self.owner );
  317.         if (trace_fraction < 1 ) goal = trace_endpos + '0 0 6';
  318.     }
  319.     ////////////////////////////////////////
  320.  
  321.     self.angles = self.owner.angles;
  322.  
  323.     traceline (self.origin, owner_vec, FALSE, self.owner );
  324.     if (trace_fraction == 1)
  325.     {
  326.         dir = normalize(goal - self.origin);
  327.         dist = vlen(goal - self.origin);
  328.  
  329.         cap = dist * 0.16;
  330.  
  331.         if (cap > 5.2)
  332.             self.velocity = dir * dist * 5.2;
  333.         else if (cap > 1)
  334.             self.velocity = dir * dist * cap;
  335.         else
  336.             self.velocity = dir * dist;
  337.  
  338.         // tighten up if owner running backwards
  339.         if (f_f > 560)
  340.         {
  341.             //if (self.owner.v_angle_x < -42)
  342.             //    self.velocity = self.velocity * 2.6;
  343.             //else
  344.             //    self.velocity = self.velocity * 1.4;
  345.             self.velocity = self.velocity * 2;
  346.         }
  347.         // try to avoid hangups common to ceiling clips when player
  348.         // is running
  349.         if( self.oldorigin == self.origin )
  350.         {
  351.             if( dist > 16 )
  352.             {
  353.                 self.ammo_nails = self.ammo_nails + 1;
  354.                 if( self.ammo_nails > 2 )
  355.                 {
  356.                     self.ammo_nails = 0;
  357.                     self.velocity = '0 0 0';
  358.                     setorigin( self, goal );
  359.                 }
  360.             }
  361.             else
  362.                 self.ammo_nails = 0;
  363.         }
  364.     }
  365.     else
  366.     {
  367.         self.velocity = '0 0 0';
  368.         setorigin( self, goal );
  369.     }
  370.  
  371.     // keep flag clear so internal C won't drop movement checks
  372.     if (self.flags & FL_ONGROUND)
  373.         self.flags = self.flags - FL_ONGROUND;
  374.  
  375.     self.oldorigin = self.origin;
  376. };
  377.  
  378.  
  379. // called by player only
  380. void() Toggle_chase_cam =
  381. {
  382.  
  383.     if (self.waterlevel)
  384.         return;
  385.  
  386.     if( (self.dest2_x & CHSCAM_ON) )
  387.     {
  388.         // will be noticed by next think
  389.         // of player's chase cam entity
  390.         self.dest2_x = self.dest2_x - CHSCAM_ON;
  391.     }
  392.     else
  393.         Start_chase_cam( self, '0 0 0' );
  394.  
  395. };
  396.  
  397. ////////////////////////////////////////////
  398. // laser targeter functions
  399.  
  400. // targeter ent. think function
  401. void() LaserTargeterTrack = {
  402.     local vector src;
  403.  
  404.     self.nextthink = time + 0.05;
  405.  
  406.     if (! (self.owner.dest2_x & LASERTARG_ON))
  407.     {
  408.         if( (self.owner.dest2_x & LASERTARG_LIT) )
  409.         {
  410.             self.owner.dest2_x = self.owner.dest2_x | LASERTARG_ON;
  411.             self.effects = self.effects | EF_DIMLIGHT;
  412.         }
  413.         else
  414.         {
  415.             remove( self );
  416.             return;
  417.         }
  418.     }
  419.  
  420.     if (self.owner.solid == SOLID_NOT)
  421.     {
  422.         // leave .dest2_x flags alone
  423.         remove( self );
  424.         return;
  425.     }
  426.  
  427.     if (self.owner.weapon == IT_AXE)
  428.     {
  429.         if (self.model != "")
  430.             setmodel( self, "" );
  431.     }
  432.     else if (self.model == "")
  433.         setmodel( self, "progs/cross1.mdl" );
  434.  
  435.     makevectors( self.owner.v_angle );
  436.     self.angles = vectoangles( v_forward );
  437.  
  438.     src = self.owner.origin + v_forward * 10;
  439.     src_z = self.owner.absmin_z + self.owner.size_z * 0.7;
  440.  
  441.     traceline( src,  src + v_forward * 2048, FALSE, self.owner);
  442.  
  443.     setorigin( self, (0.1 * src + 0.9 * trace_endpos) );
  444.  
  445.  
  446. };
  447.  
  448. void( entity targ_owner ) LaserTargeterToggle =
  449. {
  450.  
  451.     local entity e;
  452.  
  453.     if( (targ_owner.dest2_x & LASERTARG_ON) )
  454.     {
  455.         // don't activate glow in multi-player
  456.         if (! deathmatch  && ! coop)
  457.         {
  458.             if( (targ_owner.dest2_x & LASERTARG_LIT) )
  459.                 targ_owner.dest2_x = targ_owner.dest2_x - LASERTARG_LIT;
  460.             else
  461.                 targ_owner.dest2_x = targ_owner.dest2_x | LASERTARG_LIT;
  462.         }
  463.  
  464.         targ_owner.dest2_x = targ_owner.dest2_x - LASERTARG_ON;
  465.     }
  466.     else
  467.     {
  468.         targ_owner.dest2_x = targ_owner.dest2_x | LASERTARG_ON;
  469.  
  470.         e = spawn();
  471.         e.owner = targ_owner;
  472.  
  473.         e.movetype = MOVETYPE_NONE;
  474.         e.solid = SOLID_NOT;
  475.  
  476.         // setmodel( e, "progs/s_bubble.spr" );
  477.         setmodel( e, "progs/cross1.mdl" );
  478.         setsize( e, VEC_ORIGIN, VEC_ORIGIN );
  479.         setorigin( e, e.owner.origin );
  480.  
  481.         if( (e.owner.dest2_x & LASERTARG_LIT) )
  482.             e.effects = e.effects | EF_DIMLIGHT;
  483.  
  484.         e.nextthink = time + 0.1;
  485.         e.think = LaserTargeterTrack;
  486.  
  487.     }
  488.  
  489. };
  490. ////////////////////////////////////////////
  491.  
  492. void () Spawn_extra_changelevels;
  493. void() Chase_cam_lvlstart_think =
  494. {
  495.     self.owner.skin = self.owner.dest1_y; //mskin pro stuff
  496.  
  497.     if ( (self.owner.dest2_x & CHSCAM_ON) )
  498.         Start_chase_cam( self.owner, '0 0 0' );
  499.  
  500.     if ( (self.owner.dest2_x & LASERTARG_ON) )
  501.     {
  502.         self.owner.dest2_x = self.owner.dest2_x - LASERTARG_ON;
  503.         LaserTargeterToggle( self.owner );
  504.     }
  505.  
  506.     if (world.model == "maps/start.bsp")
  507.         Spawn_extra_changelevels();
  508.  
  509.     remove( self );
  510. };
  511.  
  512.  
  513. // called in CLIENT.QC by void() PutClientInServer
  514. // player.dest2_x is set and saved between levels using parm16
  515. // in CLIENT.QC
  516. void() Chase_cam_level_start =
  517. {
  518.  
  519.     local entity e;
  520.  
  521.     e = spawn();
  522.     e.owner = self;
  523.     e.nextthink = time + 0.2;
  524.     e.think = Chase_cam_lvlstart_think;
  525.  
  526. };
  527.  
  528.  
  529. // opt:
  530. // 0 = minus
  531. // 1 = plus
  532. // 2 = read cvar temp1 for value
  533. // (player.dest2_y holds cam distance)
  534. void(float opt) Chase_cam_change_dist =
  535. {
  536.     local string s;
  537.  
  538.     if (!opt)
  539.     {
  540.         self.dest2_y = self.dest2_y - 2;
  541.         if (self.dest2_y < 10)
  542.             self.dest2_y = 10;
  543.     }
  544.     else if (opt == 1)
  545.         self.dest2_y = self.dest2_y + 2;
  546.     else
  547.         self.dest2_y = cvar( "temp1" );
  548.  
  549.     sprint( self, "chasecam distance = " );
  550.     s = ftos( self.dest2_y );
  551.     sprint( self, s );
  552.     sprint( self, "\n" );
  553.  
  554.  
  555. };
  556.  
  557. // opt:
  558. // 0 = minus
  559. // 1 = plus
  560. // 2 = read cvar temp1 for value
  561. // (player.dest2_z holds zmult)
  562. void(float opt) Chase_cam_change_zmult =
  563. {
  564.     local string str;
  565.     local float f;
  566.  
  567.     if (!opt)
  568.     {
  569.         self.dest2_z = self.dest2_z - 0.02;
  570.         if (self.dest2_z < 0)
  571.             self.dest2_z = 0;
  572.     }
  573.     else if (opt == 1)
  574.         self.dest2_z = self.dest2_z + 0.02;
  575.     else
  576.     {
  577.         f = cvar( "temp1" );
  578.         self.dest2_z = f * 0.01;
  579.     }
  580.  
  581.     sprint( self, "chasecam verticle offset = " );
  582.  
  583.     // convert and strip for display
  584.     // apparantly,
  585.     //    .dest2_z = .dest2_z +- 0.02;
  586.     // don't _exactly_ add/sub 0.02
  587.     f = self.dest2_z * 100;
  588.     f = rint( f );
  589.     str = ftos( f );
  590.  
  591.     sprint( self, str );
  592.     sprint( self, "\n" );
  593.  
  594.  
  595. };
  596.  
  597. /*
  598. Reads current values of cvar temp1:
  599. opt:
  600.     0 = into player.dest2_y (chasecam distance)
  601.     1 = into player.dest2_z (zmult)
  602. */
  603. void(float opt) Chase_cam_read_temp1 =
  604. {
  605.     if (!opt)
  606.         Chase_cam_change_dist(2);
  607.     else
  608.         Chase_cam_change_zmult(2);
  609. };
  610.  
  611. // ### chase cam mod ###
  612. // #####################
  613.  
  614. // ###############
  615. // ### HUD mod ###
  616.  
  617. /*
  618. player.dest1_x
  619.  
  620. to hold last player.health for automaticly printing health changes.
  621.  
  622.  Axe, Sh, D_brl, Nl, S_Nl, Grnd, Rckt, Ltng
  623. .armortype  (0.3, 0.6, 0.8)
  624. .armorvalue
  625. .currentammo
  626. .weapon
  627. */
  628.  
  629.  
  630. // opt:
  631. // 0 = print only health
  632. // 1 = print full status
  633. // called only by player in ImpulseCommands() and   W_WeaponFrame()
  634. void( float opt ) HUD_print_info =
  635. {
  636.     local string str;
  637.     local float cap, c, c2, c_inc;
  638.  
  639.     if (! (self.dest2_x & HUD_ON) ) return;
  640.  
  641.     if (opt == 1) // player selected full update
  642.     {
  643.         self.dest1_x = self.health;
  644.  
  645.         // ammo
  646.         c2 = 15;
  647.         if (self.ammo_shells  > 9.5 ) c2 = c2 - 0.5;
  648.         if (self.ammo_shells  > 99.5) c2 = c2 - 0.5;
  649.         if (self.ammo_nails   > 9.5 ) c2 = c2 - 0.5;
  650.         if (self.ammo_nails   > 99.5) c2 = c2 - 0.5;
  651.         if (self.ammo_rockets > 9.5 ) c2 = c2 - 0.5;
  652.         if (self.ammo_rockets > 99.5) c2 = c2 - 0.5;
  653.         if (self.ammo_cells   > 9.5 ) c2 = c2 - 0.5;
  654.         if (self.ammo_cells   > 99.5) c2 = c2 - 0.5;
  655.         c = 0;
  656.         while (c < c2) {sprint( self, " " ); c = c + 1;}
  657.  
  658.         str = ftos( self.ammo_shells );
  659.             sprint( self, str );
  660.             sprint( self, "Ä");
  661.         str = ftos( self.ammo_nails );
  662.             sprint( self, str );
  663.             sprint( self, "Ä");
  664.         str = ftos( self.ammo_rockets );
  665.             sprint( self, str );
  666.             sprint( self, "Ä");
  667.         str = ftos( self.ammo_cells );
  668.             sprint( self, str );
  669.  
  670.         // armor                                  1234 : 33 left
  671.         if      (self.armortype > 0.78) {str = "\nâââ "; cap = 200;}
  672.         else if (self.armortype > 0.58) {str = "\nââ  "; cap = 150;}
  673.         else if (self.armortype > 0.28) {str = "\nâ   "; cap = 100;}
  674.         else                            {str = "\n    "; cap = 0;}
  675.         sprint( self, str );
  676.  
  677.         if (cap > 0.5)
  678.         {
  679.             c_inc = cap * 0.0303;
  680.             c = c_inc;
  681.             sprint( self, "¥" );
  682.             c2 = 0;
  683.             while (c2 < 32)
  684.             {
  685.                 c = c + c_inc;
  686.                 if (c < self.armorvalue)
  687.                 {
  688.                     if (c > (cap - c_inc) )
  689.                         sprint( self, "ƒ" );
  690.                     else
  691.                         sprint( self, "₧" );
  692.                 }
  693.                 c2 = c2 + 1;
  694.             }
  695.  
  696.         }
  697.  
  698.         sprint( self, "\n" );
  699.     }
  700.     else // automatic health print
  701.     {
  702.         cap = self.dest1_x;
  703.         self.dest1_x = self.health;
  704.  
  705.         // don't print health rots
  706.         if (self.health > 100.5 && cap == self.health + 1) return;
  707.  
  708.         sprint( self, "\n\n" );
  709.     }
  710.  
  711.     c = 2.777;
  712.     cap = self.health;
  713.     if (cap > 100 - c ) cap = 100 - c;
  714.  
  715.     sprint( self, "Ç" );
  716.     while (c < cap)
  717.     {
  718.         sprint( self, "ü" );
  719.         c = c + 2.777;
  720.     }
  721.     if (self.health > 99.5)
  722.         sprint( self, "é" );
  723.  
  724.     if (opt == 1)
  725.     {
  726.         if (self.items & IT_KEY1) sprint( self, "\nS" );
  727.         else                      sprint( self, "\n " );
  728.         if (self.items & IT_KEY2) sprint( self, "G" );
  729.         else                      sprint( self, " " );
  730.  
  731.  
  732.         if ( (self.dest2_x & CHSCAM_ON) )
  733.         {
  734.                   if (self.weapon == IT_SHOTGUN)                str = "   Shotgun    ";
  735.             else if (self.weapon == IT_SUPER_SHOTGUN)     str = "   Dbl Brl    ";
  736.             else if (self.weapon == IT_NAILGUN)             str = "   Nailgun    ";
  737.             else if (self.weapon == IT_SUPER_NAILGUN)     str = "   Sup Nailgun";
  738.             else if (self.weapon == IT_GRENADE_LAUNCHER) str = "   Grenades   ";
  739.             else if (self.weapon == IT_ROCKET_LAUNCHER)     str = "   Rockets    ";
  740.             else if (self.weapon == IT_LIGHTNING)            str = "   Lghtng Gun ";
  741.             else //(self.weapon == IT_AXE)
  742.                                                                         str = "   Axe        ";
  743.         }
  744.         else                                                            str = "              ";
  745.  
  746.         sprint( self, str );
  747.  
  748.     }
  749.     else
  750.         sprint( self, "\n                " );
  751.  
  752.  
  753.     if (self.health < 100.5)
  754.         sprint( self, "\n" );
  755.     else
  756.     {
  757.                         // kkwwwwwwwwwwwwww
  758.                       //  123456789.123456789.123456789.1234567
  759.         sprint( self,                 "               " );
  760.         c = 225;
  761.         while (c > 99) // 225 200 175 150 125 100
  762.         {
  763.             if (self.health > c)
  764.                 sprint( self, "Ä" );
  765.             else
  766.                 sprint( self, " " );
  767.             c = c - 25;
  768.         }
  769.         sprint( self, "\n" );
  770.     }
  771.  
  772. };
  773.  
  774. // ### HUD mod ###
  775. // ###############
  776.  
  777.  
  778.  
  779.  
  780.  
  781. /*
  782.  ######################
  783.  ### Multiskin Pro ###
  784.  
  785.  player.dest1_y   holds real current skin at all times
  786.                         (for powerup changes to use when switching back)
  787.  
  788.  Orig. functions modifyed:
  789.     WEAPONS.QC
  790.         ImpulseCommands
  791.     CLIENT.QC
  792.         PutClientInServer
  793.  
  794. */
  795.  
  796. // opt:
  797. // 0 = up
  798. // 1 = down
  799. void( float opt ) Choose_multiskin =
  800. {
  801.     if (opt == 0)
  802.     {
  803.         self.dest1_y = self.dest1_y + 1;
  804.         if (self.dest1_y > 20)
  805.             self.dest1_y = 0;
  806.     }
  807.     else
  808.     {
  809.         self.dest1_y = self.dest1_y - 1;
  810.         if (self.dest1_y < 0)
  811.             self.dest1_y = 20;
  812.     }
  813.  
  814.     self.skin = self.dest1_y;
  815.  
  816.     if (self.skin == 0)
  817.         centerprint(self, "QUAKE GUY (1)");
  818.     else if (self.skin == 1)
  819.         centerprint(self, "DUKE NUKEM 3D (2)");
  820.     else if (self.skin == 2)
  821.         centerprint(self, "DARK TOAD (3)");
  822.     else if (self.skin == 3)
  823.         centerprint(self, "STORMTROOPER (4)");
  824.     else if (self.skin == 4)
  825.         centerprint(self, "HAN SOLO (5)");
  826.     else if (self.skin == 5)
  827.         centerprint(self, "TERMINATOR (6)");
  828.     else if (self.skin == 6)
  829.         centerprint(self, "JUDGE DREDD (7)");
  830.     else if (self.skin == 7)
  831.         centerprint(self, "C3PO (8)");
  832.     else if (self.skin == 8)
  833.         centerprint(self, "CAPTAIN PICARD (9)");
  834.     else if (self.skin == 9)
  835.         centerprint(self, "BOSSK (10)");
  836.     else if (self.skin == 10)
  837.         centerprint(self,"PREDATOR (11)");
  838.     else if (self.skin == 11)
  839.         centerprint(self,"SKELETON (12)");
  840.     else if (self.skin == 12)
  841.         centerprint(self,"WAN FU (13)");
  842.     else if (self.skin == 13)
  843.         centerprint(self,"HENRY ROLLINS (14)");
  844.     else if (self.skin == 14)
  845.         centerprint(self,"DOOM GRUNT (15)");
  846.     else if (self.skin == 15)
  847.         centerprint(self,"BOBA FETT (16)");
  848.     else if (self.skin == 16)
  849.         centerprint(self,"NYPD BLUE (17)");
  850.     else if (self.skin == 17)
  851.         centerprint(self,"QUAKE ENFORCER (18)");
  852.     else if (self.skin == 18)
  853.         centerprint(self,"JASON (19)");
  854.     else if (self.skin == 19)
  855.         centerprint(self,"O.J. (20)");
  856.     else if (self.skin == 20)
  857.         centerprint(self,"The CROW (21)");
  858.     //else if (self.skin == 21)
  859.     //    centerprint(self,"QUAKE BIOSUIT (22)");
  860. };
  861. // ### Multiskin v1.1 ###
  862. // ######################
  863.  
  864. /*
  865.  #######################
  866.  ### Hot Key Weapons ###
  867.  
  868.  player.dest_x
  869.  
  870.  Rob Albin, Oct 7 96
  871.  
  872.  Orig. functions modifyed:
  873.     WEAPONS.QC
  874.         ImpulseCommands
  875.  
  876.  Abstract:
  877.     Provides hot-key impulses for axe, grenade, and rocket launcher
  878.     that return to previous weapon.
  879.     New cycle weapons impulses that don't select these weapons.
  880.  
  881.     uses free player entity variable (float point of vector) dest_x
  882.     (only used for doors)
  883.  
  884.  
  885.  CFG file use:
  886.  
  887.  alias +axe_hotkey "impulse 41; +attack"
  888.  alias -axe_hotkey "impulse 40; -attack"
  889.  
  890.  alias +grenade_hotkey "impulse 42; +attack"
  891.  alias -grenade_hotkey "impulse 40; -attack"
  892.  
  893.  alias +rocket_hotkey "impulse 43; +attack"
  894.  alias -rocket_hotkey "impulse 40; -attack"
  895.  
  896.  bind "<key>" "+axe_hotkey"
  897.  bind "<key>" "+grenade_hotkey"
  898.  bind "<key>" "+rocket_hotkey"
  899.  
  900.  // new weapons cycle commands (skips hot-key weapons)
  901.  bind "<key>" "impulse 44"
  902.  bind "<key>" "impulse 45"
  903.  
  904. */
  905.  
  906.  
  907. // opt:
  908. // 1 = axe
  909. // 2 = grenade launcher
  910. // 3 = rocket launcher
  911. void( float opt ) HotKey_weapon =
  912. {
  913.     local float w;
  914.  
  915.     if (self.weapon != IT_GRENADE_LAUNCHER &&
  916.          self.weapon != IT_ROCKET_LAUNCHER  &&
  917.          self.weapon != IT_AXE)
  918.         self.dest_x = self.weapon;
  919.  
  920.     if (opt == 1)
  921.     {    w = IT_AXE;
  922.     }
  923.     else if (opt == 2)
  924.     {  if (! (self.items & IT_GRENADE_LAUNCHER) ) return;
  925.         w = IT_GRENADE_LAUNCHER;
  926.     }
  927.     else
  928.     {  if (! (self.items & IT_ROCKET_LAUNCHER) ) return;
  929.         w = IT_ROCKET_LAUNCHER;
  930.     }
  931.  
  932.     self.weapon = w;
  933.     W_SetCurrentAmmo();
  934. };
  935.  
  936. void() HotKey_previous_weapon =
  937. {
  938.     if (! self.dest_x)
  939.         return;
  940.  
  941.     self.weapon = self.dest_x;
  942.     W_SetCurrentAmmo();
  943. };
  944.  
  945. void() HotKey_CycleWeaponCommand =
  946. {
  947.     local float w, it, am, c;
  948.  
  949.     c = 0;
  950.     w = self.weapon;
  951.  
  952.     it = self.items;
  953.     self.impulse = 0;
  954.  
  955.     while (1)
  956.     {
  957.         am = 0;
  958.  
  959.         if (w == IT_AXE)
  960.         {  w = IT_SHOTGUN;
  961.             if (self.ammo_shells < 1) am = 1;
  962.         }
  963.         else if (w == IT_SHOTGUN)
  964.         {  w = IT_SUPER_SHOTGUN;
  965.             if (self.ammo_shells < 2) am = 1;
  966.         }
  967.         else if (w == IT_SUPER_SHOTGUN)
  968.         {  w = IT_NAILGUN;
  969.             if (self.ammo_nails < 1) am = 1;
  970.         }
  971.         else if (w == IT_NAILGUN)
  972.         {  w = IT_SUPER_NAILGUN;
  973.             if (self.ammo_nails < 2) am = 1;
  974.         }
  975.         else if (w == IT_SUPER_NAILGUN)
  976.         {  w = IT_LIGHTNING;
  977.             if (self.ammo_cells < 1) am = 1;
  978.         }
  979.         else if (w == IT_GRENADE_LAUNCHER)
  980.         {  w = IT_LIGHTNING;
  981.             if (self.ammo_cells < 1) am = 1;
  982.         }
  983.         else if (w == IT_ROCKET_LAUNCHER)
  984.         {  w = IT_LIGHTNING;
  985.             if (self.ammo_cells < 1) am = 1;
  986.         }
  987.         else if (w == IT_LIGHTNING)
  988.         {  w = IT_SHOTGUN;
  989.             if (self.ammo_shells < 1) am = 1;
  990.         }
  991.  
  992.         if ( (it & w) && am == 0)
  993.         {
  994.             self.weapon = w;
  995.             W_SetCurrentAmmo ();
  996.             return;
  997.         }
  998.  
  999.         if (c > 9) return;
  1000.         c = c + 1;
  1001.     }
  1002.  
  1003. };
  1004.  
  1005.  
  1006. void() HotKey_CycleWeaponReverseCommand =
  1007. {
  1008.     local float w, it, am, c;
  1009.  
  1010.     c = 0;
  1011.     w = self.weapon;
  1012.  
  1013.     it = self.items;
  1014.     self.impulse = 0;
  1015.  
  1016.     while (1)
  1017.     {
  1018.         am = 0;
  1019.  
  1020.         if (w == IT_LIGHTNING)
  1021.         {    w = IT_SUPER_NAILGUN;
  1022.             if (self.ammo_nails < 2) am = 1;
  1023.         }
  1024.         else if (w == IT_ROCKET_LAUNCHER)
  1025.         {    w = IT_SUPER_NAILGUN;
  1026.             if (self.ammo_nails < 2) am = 1;
  1027.         }
  1028.         else if (w == IT_GRENADE_LAUNCHER)
  1029.         {    w = IT_SUPER_NAILGUN;
  1030.             if (self.ammo_nails < 2) am = 1;
  1031.         }
  1032.         else if (w == IT_SUPER_NAILGUN)
  1033.         {    w = IT_NAILGUN;
  1034.             if (self.ammo_nails < 1) am = 1;
  1035.         }
  1036.         else if (w == IT_NAILGUN)
  1037.         {    w = IT_SUPER_SHOTGUN;
  1038.             if (self.ammo_shells < 2) am = 1;
  1039.         }
  1040.         else if (w == IT_SUPER_SHOTGUN)
  1041.         {    w = IT_SHOTGUN;
  1042.             if (self.ammo_shells < 1) am = 1;
  1043.         }
  1044.         else if (w == IT_SHOTGUN)
  1045.         {  w = IT_LIGHTNING;
  1046.             if (self.ammo_cells < 1) am = 1;
  1047.         }
  1048.         else if (w == IT_AXE)
  1049.         {  w = IT_LIGHTNING;
  1050.             if (self.ammo_cells < 1) am = 1;
  1051.         }
  1052.  
  1053.         if ( (it & w) && am == 0)
  1054.         {
  1055.             self.weapon = w;
  1056.             W_SetCurrentAmmo ();
  1057.             return;
  1058.         }
  1059.  
  1060.         if (c > 9) return;
  1061.         c = c + 1;
  1062.     }
  1063.  
  1064. };
  1065.  
  1066. // ### Hot Key Weapons mod ###
  1067. // ###########################
  1068.  
  1069.  
  1070. // #########################
  1071. // ### Start.bsp Marquee ###
  1072.  
  1073. void () S_E_CLVLS_marquee =
  1074. {
  1075.     self.nextthink = time + 1;
  1076.     self.ammo_shells = self.ammo_shells + 1;
  1077.     centerprint( self.owner, "¡ ├Φß≤σπßφ ╔╔ QuakeC mod ¡\n\n¡  written by Rob Albin  ¡" );
  1078.     if (self.ammo_shells > 3)
  1079.         remove( self );
  1080. };
  1081.  
  1082. // float S_E_CLVLS_flag;
  1083. void () Spawn_extra_changelevels =
  1084. {
  1085.     local float i;
  1086.     local entity e;
  1087.  
  1088.     if (time < 10)
  1089.     {
  1090.         e = spawn();
  1091.         e.owner = self.owner;
  1092.         e.nextthink = time + 3;
  1093.         e.think = S_E_CLVLS_marquee;
  1094.     }
  1095.  
  1096. };
  1097.  
  1098.  
  1099.  
  1100.  
  1101.